package com.kettle.service.quart.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.matchers.GroupMatcher;
import org.quartz.impl.matchers.KeyMatcher;
import org.springframework.stereotype.Service;

import com.kettle.filter.QuartzListener;
import com.kettle.model.quartz.JobDto;
import com.kettle.model.quartz.ReturnResult;
import com.kettle.model.rowpage.PageResult;
import com.kettle.service.quart.QuartzService;
import com.kettle.utils.DateTime;

/**
 * 定时任务管理
 * @author king
 */
@Service("quartzService")
public class QuartzServiceImpl implements QuartzService {

	@Resource
    private Scheduler quartzScheduler;

	/**
	 * 添加工作任务
	 */
    @SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
    public ReturnResult addJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName, Class cls, String cron) {
    	ReturnResult result=new ReturnResult();
    	result.setCode("500");
    	result.setSuccess(false);
    	try {
            // 获取调度器
            Scheduler sched = quartzScheduler;
            // 创建一项作业
            // 任务名，任务组，任务执行类
            JobDetail job = JobBuilder.newJob(cls).withIdentity(jobName, jobGroupName).build();
            JobDataMap map = job.getJobDataMap();
            map.put("key", "jobName");
            // 触发器  
            TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
            // 触发器名,触发器组  
            triggerBuilder.withIdentity(triggerName, triggerGroupName);
            triggerBuilder.startNow();
            // 触发器时间设定  
            triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
            // 创建Trigger对象
            CronTrigger trigger = (CronTrigger) triggerBuilder.build();
            // 创建一个触发器
            //CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(triggerName, triggerGroupName).withSchedule(CronScheduleBuilder.cronSchedule(cron)).build();
            // 告诉调度器使用该触发器来安排作业
            sched.scheduleJob(job, trigger);
            //如果已经停止启动该调度
            if (!sched.isShutdown()) {
                sched.start();
            }
            result.setCode("200");
            result.setSuccess(true);
            result.setMsg("添加成功");
        } catch (Exception e) {
        	result.setMsg("添加失败："+e.getMessage());
            throw new RuntimeException(e);
        }
    	return result;
    }
    /**
     * 立即执行
     * @param jobName
     * @param jobGroupName
     * @param triggerName
     * @param triggerGroupName
     * @param jobClass
     * @param parameter
     */
    @Override
    public void addOnceJob(String jobName, String jobGroupName, 
            String triggerName, String triggerGroupName, Class cls, 
            Map<String, Object> parameter){
    	try {
    		Scheduler sched = quartzScheduler;
    		// 任务名，任务组，任务执行类
            JobDetail jobDetail = JobBuilder.newJob(cls).withIdentity(jobName, jobGroupName).build();
            // 添加任务执行的参数
            if(parameter!=null) {
	            parameter.forEach((k, v) -> {
	            	jobDetail.getJobDataMap().put(k, v);
	            });
            }
            // 触发器
            TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
            // 触发器名,触发器组
            triggerBuilder.withIdentity(triggerName, triggerGroupName);
            triggerBuilder.startNow();
            //立即执行
            StringBuilder cronBuilder = new StringBuilder();
    		DateTime dateTime = new DateTime();
    		Integer addMinute = dateTime.second() >= 58 ? 2 : 1;
    		cronBuilder.append("0").append(" ")
    						.append(dateTime.minute() + addMinute).append(" ")
    						.append(dateTime.hour(true)).append(" ")
    						.append(dateTime.dayOfMonth()).append(" ")
    						.append(dateTime.monthStartFromOne()).append(" ")
    						.append("?").append(" ")
    						.append(String.valueOf(dateTime.year()));
            // 触发器时间设定
            triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cronBuilder.toString()));
            // 创建Trigger对象
            CronTrigger trigger = (CronTrigger) triggerBuilder.build();
            // 调度容器设置JobDetail和Trigger
            sched.scheduleJob(jobDetail, trigger);
            // 添加任务执行监听器
            sched.getListenerManager().addJobListener(new QuartzListener(), 
            		KeyMatcher.keyEquals(new JobKey(jobName, jobGroupName)));
            // 启动  
            if (!sched.isShutdown()) {  
                sched.start();  
            }             
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 修改定时器任务信息
     */
    @SuppressWarnings("rawtypes")
	@Override
    public ReturnResult modifyJobTime(String oldjobName, String oldjobGroup, String oldtriggerName, String oldtriggerGroup, 
    		String jobName, String jobGroup, String triggerName, String triggerGroup, String cron) {
    	ReturnResult result=new ReturnResult();
    	result.setCode("500");
    	result.setSuccess(false);
    	try {
            Scheduler sched = quartzScheduler;
            CronTrigger trigger = (CronTrigger) sched.getTrigger(TriggerKey.triggerKey(oldtriggerName, oldtriggerGroup));
            if (trigger == null) {
            	result.setMsg("获取不到触发器:"+triggerName);
                return result;
            }
            String oldTime = trigger.getCronExpression(); //获取旧的cron定时器 
            //if (!oldTime.equalsIgnoreCase(cron)) { 
            	JobKey jobKey = JobKey.jobKey(oldjobName, oldjobGroup);
                TriggerKey triggerKey = TriggerKey.triggerKey(oldtriggerName, oldtriggerGroup);
                JobDetail job = sched.getJobDetail(jobKey);
                Class jobClass = job.getJobClass();
                // 停止触发器
                sched.pauseTrigger(triggerKey);
                // 移除触发器
                sched.unscheduleJob(triggerKey);
                // 删除任务
                sched.deleteJob(jobKey);
                //重新加入job
                addJob(jobName, jobGroup, triggerName, triggerGroup, jobClass, cron);
            //}
            result.setSuccess(true);
            result.setCode("200");
            result.setMsg("修改成功");
        } catch (Exception e) {
        	result.setMsg("修改失败:"+e.getMessage());
            throw new RuntimeException(e);
        }
    	return result;
    }
    /**
     * 修改触发器调度时间
     */
    @Override
    public ReturnResult modifyJobTime(String triggerName, String triggerGroupName, String time) {
    	ReturnResult result=new ReturnResult();
    	result.setCode("500");
    	result.setSuccess(false);
    	try {
            Scheduler sched = quartzScheduler;
            CronTrigger trigger = (CronTrigger) sched.getTrigger(TriggerKey.triggerKey(triggerName, triggerGroupName));
            if (trigger == null) {
            	result.setMsg("获取不到触发器:"+triggerName);
                return result;
            }
            String oldTime = trigger.getCronExpression();
            if (!oldTime.equalsIgnoreCase(time)) {
                CronTrigger ct = (CronTrigger) trigger;
                // 修改时间
                ct.getTriggerBuilder().withSchedule(CronScheduleBuilder.cronSchedule(time)).build();
                // 重启触发器
                sched.resumeTrigger(TriggerKey.triggerKey(triggerName, triggerGroupName));
            }
            result.setSuccess(true);
            result.setCode("200");
            result.setMsg("修改成功");
        } catch (Exception e) {
        	result.setMsg("修改失败:"+e.getMessage());
            throw new RuntimeException(e);
        }
    	return result;
    }

    @Override
    public ReturnResult removeJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName) {
    	ReturnResult result=new ReturnResult();
    	result.setCode("500");
    	result.setSuccess(false);
    	try {
    		Scheduler sched = quartzScheduler;
            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
            sched.pauseTrigger(triggerKey);// 停止触发器  
            sched.unscheduleJob(triggerKey);// 移除触发器  
            sched.deleteJob(JobKey.jobKey(jobName, jobGroupName));// 删除任务  
            result.setSuccess(true);
            result.setCode("200");
            result.setMsg("删除成功");
        } catch (Exception e) {
        	result.setMsg("删除失败:"+e.getMessage());
            throw new RuntimeException(e);
        }
    	return result;
    }
	/**
	 * 开启
	 */
    @Override
    public ReturnResult startSchedule() {
    	ReturnResult result=new ReturnResult();
    	result.setCode("500");
    	result.setSuccess(false);
    	try {
            Scheduler sched = quartzScheduler;
            if (sched.isShutdown()) {
	            sched.standby(); 
	            sched.start();
            }
            result.setSuccess(true);
            result.setCode("200");
            result.setMsg("开启成功");
        } catch (Exception e) {
        	result.setMsg("开启失败:"+e.getMessage());
            throw new RuntimeException(e);
        }
    	return result;
    }
    /**
     * 停止全部
     */
    @Override
    public ReturnResult shutdownSchedule() {
    	ReturnResult result=new ReturnResult();
    	result.setCode("500");
    	result.setSuccess(false);
    	try {
            Scheduler sched = quartzScheduler;
            if (!sched.isShutdown()) {
                sched.shutdown();
            }
            result.setSuccess(true);
            result.setCode("200");
            result.setMsg("停止成功");
        } catch (Exception e) {
        	result.setMsg("停止失败:"+e.getMessage());
            throw new RuntimeException(e);
        }
    	return result;
    }

    @Override
    public ReturnResult pauseJob(String jobName, String jobGroupName) {
    	ReturnResult result=new ReturnResult();
    	result.setCode("500");
    	result.setSuccess(false);
    	try {
            quartzScheduler.pauseJob(JobKey.jobKey(jobName, jobGroupName));
            result.setSuccess(true);
            result.setCode("200");
            result.setMsg("暂停任务"+jobName+"成功");
        } catch (SchedulerException e) {
        	result.setMsg("暂停任务"+jobName+"失败:"+e.getMessage());
            e.printStackTrace();
        }
    	return result;
    }

    @Override
    public ReturnResult resumeJob(String jobName, String jobGroupName) {
    	ReturnResult result=new ReturnResult();
    	result.setCode("500");
    	result.setSuccess(false);
    	try {
            quartzScheduler.resumeJob(JobKey.jobKey(jobName, jobGroupName));
            result.setSuccess(true);
            result.setCode("200");
            result.setMsg("恢复任务"+jobName+"成功");
        } catch (SchedulerException e) {
        	result.setMsg("恢复任务"+jobName+"失败:"+e.getMessage());
            e.printStackTrace();
        }
    	return result;
    }
    
    @Override
    public PageResult getSchedulerJobInfo() throws SchedulerException {
    	PageResult klist=new PageResult();
        List<JobDto> jobInfos = new ArrayList<JobDto>();
        if(quartzScheduler.isShutdown()){
        	return null;
        }
        List<String> triggerGroupNames = quartzScheduler.getTriggerGroupNames();
        for (String triggerGroupName : triggerGroupNames) {
            Set<TriggerKey> triggerKeySet = quartzScheduler.getTriggerKeys(GroupMatcher.triggerGroupEquals(triggerGroupName));
            for (TriggerKey triggerKey : triggerKeySet) {
                Trigger t = quartzScheduler.getTrigger(triggerKey);
                if (t instanceof CronTrigger) {
                    CronTrigger trigger = (CronTrigger) t;
                    JobKey jobKey = trigger.getJobKey();
                    JobDetail jd = quartzScheduler.getJobDetail(jobKey);
                    JobDto jobInfo = new JobDto();
                    jobInfo.setJobName(jobKey.getName());
                    jobInfo.setJobGroupName(jobKey.getGroup());
                    jobInfo.setTriggerName(triggerKey.getName());
                    jobInfo.setTriggerGroupName(triggerKey.getGroup());
                    jobInfo.setCronExpression(trigger.getCronExpression());
                    jobInfo.setNextFireTime(trigger.getNextFireTime());
                    jobInfo.setPreviousFireTime(trigger.getPreviousFireTime());
                    jobInfo.setStartTime(trigger.getStartTime());
                    jobInfo.setEndTime(trigger.getEndTime());
                    jobInfo.setJobClass(jd.getJobClass().getCanonicalName());
                    // jobInfo.setDuration(Long.parseLong(jd.getDescription()));
                    Trigger.TriggerState triggerState = quartzScheduler.getTriggerState(trigger.getKey());
                    jobInfo.setJobStatus(triggerState.toString());// NONE无,
                                                                  // NORMAL正常,
                                                                  // PAUSED暂停,
                                                                  // COMPLETE完全,
                                                                  // ERROR错误,
                                                                  // BLOCKED阻塞
                    JobDataMap map = quartzScheduler.getJobDetail(jobKey).getJobDataMap();
                    if (null != map && map.size() != 0) {
                        jobInfo.setCount((long) map.size());
                        jobInfo.setJobDataMap(map);
                    } else {
                        jobInfo.setJobDataMap(new JobDataMap());
                    }
                    jobInfos.add(jobInfo);
                }
            }
        }
        klist.setRows(jobInfos);
        klist.setTotal(jobInfos.size());
        return klist;
    }

}
